Skip to content

Add Inhero MR2 board variant (nRF52840/RAK4630 solar repeater) - #3132

Draft
liekmarflow wants to merge 4 commits into
meshcore-dev:devfrom
liekmarflow:feature/inhero-mr2-variant
Draft

Add Inhero MR2 board variant (nRF52840/RAK4630 solar repeater)#3132
liekmarflow wants to merge 4 commits into
meshcore-dev:devfrom
liekmarflow:feature/inhero-mr2-variant

Conversation

@liekmarflow

@liekmarflow liekmarflow commented Aug 8, 2026

Copy link
Copy Markdown

Closes #3130. Builds on #3131 (board hooks) — the diff shows both commits
until that PR is merged; I will rebase and mark this ready once it lands.

Adds the Inhero MR2, a purpose-built solar repeater platform that is in
production and shipping:
https://shop.inhero.de/en/products/inhero-mr-2-solar-mesh-repeater-board-rak4630-sx1262-mppt-red-ce-gepruft
I am the hardware manufacturer; I can test changes on real hardware and am
happy to be tagged on anything affecting this variant.

Where the code lives: the MR2's logic sits in the variant, not in core.
This PR's own commit adds 32 files and modifies none: boards/inhero_mr2.json
plus everything under variants/inhero_mr2/. Of its 6289 lines, 454 are
board and build definitions; the rest is device code: BQ25798 and INA228
drivers, battery chemistry profiles, JEITA charge control, SOC accounting,
low-voltage sleep. The core changes visible in the diff are #3131's four
no-op hooks.

Hardware: RAK4630 (nRF52840 + SX1262), BQ25798 buck/boost charger with
universal 3.6-24 V solar input and MPPT, INA228 coulomb counter, RV-3028
RTC, BME280, 45 x 40 mm, CE-certified (RED 2014/53/EU).

What the variant provides:

  • Battery chemistry profiles (Li-Ion, LiFePO4, LTO, Na-Ion) with JEITA
    temperature-controlled charging and per-chemistry low-voltage thresholds,
    all configurable at runtime over the CLI and persisted across reboots
  • SOC tracking via hardware coulomb counting, 7-day energy statistics and
    a time-to-live prediction
  • Low-voltage system sleep (<500 uA) with RTC wakeup and autonomous recovery
  • board.* CLI namespace for configuration and diagnostics (uses the hooks
    from Add board hooks for periodic work and variant telemetry #3131); the full documentation set (EN/DE) is maintained in the
    vendor fork, linked from variants/inhero_mr2/README.md
  • Build environments: Inhero_MR2_repeater,
    Inhero_MR2_repeater_bridge_rs232, Inhero_MR2_sensor

Field use, not bench use: I run a part of the MeshCore repeater
infrastructure for a region in Saxony, Germany — hilltop and mining-tower
sites with links from 70 km to over 100 km, plus a number of small
birdhouse-style nodes. Almost all of them are MR2 by now, so this board
already carries a significant share of the MeshCore traffic here.

A representative small node, read out of the MeshCore app on 2026-08-19:
123 days of continuous uptime on solar, 701,487 packets sent and 2,003,527
received, 4 d 20 h of TX airtime (596 ms per packet, one packet every 15 s
on average), 35 % forward ratio, battery still at 100 %. Measured
consumption in real repeater operation is ~0.98 Wh/day.

Another unit ran 140 days before it surfaced a charge-accounting bug; that
bug is reproduced, verified on two battery chemistries, and fixed in this
branch.

Background on the design and the field failures that drove it:
https://shop.inhero.de/en/blogs/news/warum-es-das-mr2-gibt

Build and docs: all three environments build green, and the
documentation set was verified against the code (CLI replies, thresholds,
register values) before submission.

Transparency: this variant was developed with AI assistance under my
continuous engineering direction and review, followed by a full
pre-submission review pass. Stated upfront in line with this project's
position on code provenance. I manufacture this board and run it in the
field; I will keep the variant building and correct, and I am happy to be
tagged on anything that touches it.

@liekmarflow liekmarflow changed the title Feature/inhero mr2 variant Add Inhero MR-2 board variant (nRF52840/RAK4630 solar repeater) Aug 8, 2026
liekmarflow added a commit to liekmarflow/MeshCore that referenced this pull request Aug 8, 2026
…ev#3131/meshcore-dev#3132) - CONTEXT.md getrackt

Stand-Block neu: Issue + beide PRs mit Branch-Zeigern und Naechster-Schritt-
Ablauf nach Merge von meshcore-dev#3131. Ueberholte Doktrin ('kein PR-Verkehr zu
upstream') entfernt; stattdessen die Sicherungsregel: PR-Branches immer von
upstream/main schneiden. Feature-Branches als live PR-Koepfe markiert
(nicht loeschen). CONTEXT.md aus .gitignore genommen - auf main getrackt
ist sie PR-sicher, weil PR-Branches nie von Fork-main abstammen.
@liekmarflow
liekmarflow force-pushed the feature/inhero-mr2-variant branch from fd7274b to 4ec5a55 Compare August 9, 2026 19:22
@liekmarflow
liekmarflow force-pushed the feature/inhero-mr2-variant branch 2 times, most recently from 7f81a00 to 114eda0 Compare August 16, 2026 06:10
@liekmarflow liekmarflow changed the title Add Inhero MR-2 board variant (nRF52840/RAK4630 solar repeater) Add Inhero MR2 board variant (nRF52840/RAK4630 solar repeater) Aug 16, 2026
@liekmarflow
liekmarflow force-pushed the feature/inhero-mr2-variant branch 2 times, most recently from bd8a5c7 to 732262c Compare August 21, 2026 16:49
liekmarflow added a commit to liekmarflow/MeshCore that referenced this pull request Aug 21, 2026
… of the story

The "Relation to upstream" section still described the variant as a
standalone out-of-tree product fork. That has not been true since
2026-08-08: meshcore-dev#3130 (hardware request), meshcore-dev#3131 (board hooks) and meshcore-dev#3132 (the
variant itself) are open upstream, and the fork releases are the interim
until those land.

It also left the April withdrawal unexplained. The board was not available
yet and CE certification was still in progress; both are settled now, which
is the reason the variant is being proposed again.
@liekmarflow
liekmarflow changed the base branch from main to dev August 26, 2026 17:43
Two no-op virtuals on MainBoard, so a variant can do these things
without core changes:

- tick(): called from the simple_repeater and simple_sensor main loops.
  Lets a board feed its watchdog and run periodic housekeeping.
- queryBoardTelemetry(CayenneLPP&): simple_repeater asks the board for
  extra telemetry channels, gated by TELEM_PERM_ENVIRONMENT.

Variant-specific CLI is already covered by MainBoard::handleCommand(),
so this adds nothing for that.

Both defaults are no-ops, so existing variants build and behave
unchanged. Used by the Inhero MR2 variant (separate PR).
Application-specific repeater platform for autonomous off-grid
operation, in production and field-deployed:

- RAK4630 core module (nRF52840 + SX1262), 45 x 40 mm
- BQ25798 buck/boost charger: universal solar input 3.6-24V with MPPT,
  JEITA temperature-controlled charging
- INA228 coulomb counter for SOC tracking and 7-day energy statistics
- Li-ion, LiFePO4, LTO and Na-ion battery chemistry profiles
- RV-3028 RTC wakeup with low-voltage system sleep (<500uA) and
  autonomous recovery
- BME280 environment telemetry
- board.* CLI namespace for configuration and diagnostics (uses the
  board hooks from the previous PR)
- slim variant README; the full documentation set (EN/DE) is
  maintained in the vendor fork

Build environments: Inhero_MR2_repeater, Inhero_MR2_repeater_bridge_rs232,
Inhero_MR2_sensor.
Li-Ion and LiFePO4 are locked out below the BQ25798's cold threshold in
hardware, and VT1 is not configurable. Installations with a large bank on a
small panel would rather keep charging through a frost period than park until
spring, accepting the cell ageing that comes with it.

'set board.jeitaignore 1' lifts that lockout. The safety is a static gate, not
a firmware control loop: the board sleeps in SYSTEMOFF with the charger left
enabled, and no loop runs there. The override is therefore accepted only while
imax is at or below 0.02C of a batcap the user has stated, so an unattended
frozen cell never sees more than that rate.

- default off; POR and configureBaseBQ() leave TS_IGNORE cleared, so after a
  power loss the hardware guard is in charge until the stored config is applied
- a chemistry change clears it, before the charger is reconfigured
- imax and batcap keep it, but a write that would break the gate is refused
  rather than silently dropping the override
- switching it off restores the stored fmax behaviour, since configureChemistry()
  touches the JEITA registers only while JEITA is off
- TS_IGNORE stops the regulation, not the measurement: chemistries that carry
  an NTC keep reporting temperature while the override is active
- 'get board.fmax' reads N/A while JEITA is off, 'get board.conf' carries J:1

The override also drops the hot-side limit. At 0.02C that is thermally
uninteresting, but it is named in the README as part of the trade.
The TS divider was only observable through the Steinhart-Hart decode, which
makes it impossible to tell a divider question from a thermistor-curve
question. 'get board.bqdiag' now also carries what the ADC actually returned:

  TS:NORMAL TSadc:848=82.81% Rb:26982 CE:1 HIZ:0 ...

TSadc is the raw REG3F reading (count and percent of REGN), Rb the resistance
from TS to GND that this voltage implies with RT1 known -- that is the physical
quantity on the pin, with no thermistor curve involved. 'TSadc:off' means the
channel was disabled in the last conversion, so no raw value exists.

The value comes from the last completed one-shot, like the die temperature.
Run 'get board.telem' first for a fresh conversion.

Diagnostic only, no behaviour change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature request] Hardware support: Inhero MR-2 (CE-certified BQ25798/RAK4630 based solar repeater board)

1 participant